<?php
namespace classlib\imsdk;
class protocal {
	/**
	 * socket 实力信息
	 * @var socket
	 */
	private $socket;
	
	/**
	 * 数据库封装基础实例
	 * @var binproc
	 */
	private $packer;
	
	/**
	 * 定义协议包的最大容量
	 * @var int
	 */
	const PACK_MAX_SIZE = 2097152;
	
	/**
	 * 数据通信协议的构造
	 * Enter description here ...
	 * @param unknown_type $socket
	 * @param unknown_type $chnid
	 * @param unknown_type $userid
	 * @param unknown_type $signature
	 */
	public function __construct($socket) {
		$this->socket 	 = $socket;
		$this->packer    = new binproc();
	}
	
	/**
	 * 压缩包发送业务请求
	 * @param byte 0-255 $buzicode
	 * @param byte 0-255 $apiscode
	 * @param string $packdata
	 * @return int $nsize
	 */
	public function package($buzicode, $apiscode, $packdata) {
		$packer = new binproc();
		$nsize  = strlen($packdata);
		$amsg   = array();
		$amsg[] = $this->packer->write_int($nsize+2);
		$amsg[] = $this->packer->write_byte($buzicode);
		$amsg[] = $this->packer->write_byte($apiscode);
		$amsg[] = $packdata;
		$amsg   = implode('', $amsg);
		$nsize  = strlen($amsg);
		$nsize  = $this->socket->send($amsg, $nsize);
		return $nsize;
	}
	
	/**
	 * 数据加密传送
	 * @param string $skey
	 * @param string $sdata
	 */
	public static function crypt($skey, &$sdata) {
		$len  = strlen($skey);
		$slen = strlen($sdata);
		for($i=0; $i < $slen; $i++) {
			$sdata[$i] = chr(ord($sdata[$i]) ^ ord($skey[$i%$len]));
		}
	}
	
	/**
	 * 接收服务的信息返回并解析消息
	 * @return array('packsize'=>0, 'buzicode'=>0,
	 *  'apiscode'=>0, 'code'=>0, 'packdata'=>'')
	 */
	public function parse() {
		$nlen = 4;
		$str  = $this->socket->revc($nlen);
		if (!$str || strlen($str) != $nlen) {
			return false;
		}
		$res = array('buzicode'=>0, 'apiscode'=>0, 'code'=>0, 'packsize'=>0, 'packdata'=>'');
		$this->packer->__init__($str);
		$res['packsize'] = $this->packer->read_int();
		if ($res['packsize'] > self::PACK_MAX_SIZE || $res['packsize'] < 1) {
			$this->socket->flush();
		} else {
			if ($res['packsize'] > 0) {
				$packdata = $this->socket->revc($res['packsize']);
				$this->packer->__init__(substr($packdata, 0, 4));
				$res['buzicode'] = $this->packer->read_byte();
				$res['apiscode'] = $this->packer->read_byte();
				$res['code']     = $this->packer->read_sint();
				$res['packdata'] = substr($packdata, 4);
			} else {
				$res['packdata'] = "";
			}
		}
		return $res;
	}
}